<template>
  <OnlineCustomTable
    ref="table"
    :dataList="queryTableWidget.dataList"
    style="height: 100%; padding: 0px !important"
    :isEdit="form().isEdit"
    :widget="widget"
    border="full"
    :operationList="widget.operationList"
    :getTableIndex="queryTableWidget.getTableIndex"
    :sortChange="queryTableWidget.onSortChange"
    :onSelectChange="onSelectRowChange"
    :treeConfig="getTableTreeConfig"
    @operationClick="onOperationClick"
    @refresh="customQueryParams => refreshTable(false, customQueryParams)"
  >
    <template v-slot:pagination>
      <el-row
        type="flex"
        justify="end"
        style="margin-top: 16px"
        v-if="widget && widget.props.paged && getTableTreeConfig == null"
      >
        <el-pagination
          :total="queryTableWidget.totalCount"
          :current-page="queryTableWidget.currentPage"
          :page-size="queryTableWidget.pageSize"
          :page-sizes="[10, 20, 50, 100]"
          layout="total, prev, pager, next, sizes"
          @current-change="queryTableWidget.onCurrentPageChange"
          @size-change="queryTableWidget.onPageSizeChange"
        />
      </el-row>
    </template>
  </OnlineCustomTable>
</template>

<script setup lang="ts">
import { ElMessage, ElMessageBox } from 'element-plus';
import { useRouter } from 'vue-router';
import { download, post, get } from '@/common/http/request';
import { API_CONTEXT } from '@/api/config';
import { treeDataTranslate } from '@/common/utils';
import { useUpload } from '@/common/hooks/useUpload';
import { useTable } from '@/common/hooks/useTable';
import { TableOptions } from '@/common/types/pagination';
import { ANY_OBJECT } from '@/types/generic';
import OnlineCustomTable from './OnlineCustomTable.vue';
import { SysOnlineColumnFilterType, SysOnlineFieldKind } from '@/common/staticDict/online';
import { OnlineFormEventType, SysCustomWidgetOperationType } from '@/common/staticDict';

interface IProps {
  widget: ANY_OBJECT;
  masterTableData?: ANY_OBJECT;
}

const { fetchUpload } = useUpload();
const router = useRouter();
const props = withDefaults(defineProps<IProps>(), {});

const form = inject('form', () => {
  return { isEdit: false } as ANY_OBJECT;
});

const selectRows = ref<ANY_OBJECT[]>([]);
const customQueryParams = ref<ANY_OBJECT>([]);

const primaryColumnName = computed(() => {
  let table = form().tableMap.get(props.widget.bindData.tableId);
  if (table && Array.isArray(table.columnList)) {
    for (let i = 0; i < table.columnList.length; i++) {
      let column = table.columnList[i];
      if (column.primaryKey) {
        return column.columnName;
      }
    }
  }
  return null;
});

const getTableTreeConfig = computed(() => {
  if (props.widget && props.widget.props.treeFlag && props.widget.props.parentIdColumn) {
    return {
      rowField: primaryColumnName.value,
      parentField: props.widget.props.parentIdColumn,
    };
  } else {
    return null;
  }
});

const refreshTable = (reloadData = false, queryParams = undefined) => {
  customQueryParams.value = queryParams;
  if (form().isEdit) return;
  if (reloadData) {
    queryTableWidget.refreshTable(true, 1);
  } else {
    queryTableWidget.refreshTable();
  }
};

const table = ref();
const getQueryString = () => {
  if (table.value) {
    let queryTable = table.value;
    if (Array.isArray(table.value)) {
      queryTable = table.value[0].value;
    }
    if (queryTable) {
      return queryTable.getSearchString();
    }
  }
  return null;
};

const loadTableData = async (params: ANY_OBJECT) => {
  if (form().isEdit) {
    return {
      dataList: [],
      totalCount: 0,
    };
  }
  try {
    let table = form().tableMap.get(props.widget.bindData.tableId);
    if (!table) {
      console.warn('table is undefined tableId=', props.widget.bindData.tableId);
      throw new Error();
    }

    params.datasourceId = table.datasource.datasourceId;
    params.filterDtoList = [];

    if (props.widget.relation != null) {
      params.relationId = table.relation.relationId;
      params.filterDtoList.push({
        tableName: props.widget.table.tableName,
        columnName: props.widget.relation.slaveColumn.columnName,
        filterType: SysOnlineColumnFilterType.EQUAL_FILTER,
        columnValue: (props.masterTableData || {})[props.widget.relation.masterColumn.columnName],
      });
    }
    let queryString = getQueryString();
    // 模糊查询
    if (
      Array.isArray(props.widget.props.likeQueryColumn) &&
      props.widget.props.likeQueryColumn.length > 0 &&
      queryString != null &&
      queryString !== ''
    ) {
      let queryColumn = props.widget.props.likeQueryColumn
        .map(item => {
          return item.join('.');
        })
        .join(',');
      if (!Array.isArray(params.filterDtoList)) params.filterDtoList = [];
      params.filterDtoList.push({
        columnName: queryColumn,
        filterType: 14,
        columnValue: queryString,
      });
    }
    // 自定义查询
    if (customQueryParams.value != null) {
      params.customFilterGroupList = customQueryParams.value;
    }
    // 脱敏设置
    params.ignoreMaskFields = form().getIgnoreMaskFields(props.widget);
    if (form() && form().getIgnoreMaskFields)
      params.ignoreMaskFields = form().getIgnoreMaskFields(props.widget);
    if (
      !form().isEdit &&
      typeof props.widget.eventInfo[OnlineFormEventType.BEFORE_LOAD_TABLE_DATA] === 'function'
    ) {
      params = await props.widget.eventInfo[OnlineFormEventType.BEFORE_LOAD_TABLE_DATA](
        params,
        form().instanceData(),
      );
    }
    if (params == null) {
      throw new Error();
    }

    let res;
    if (table.relation != null) {
      res = await post(
        API_CONTEXT +
          '/online/onlineOperation/listByOneToManyRelationId/' +
          table.datasource.variableName,
        params,
      );
    } else {
      res = await post(
        API_CONTEXT + '/online/onlineOperation/listByDatasourceId/' + table.datasource.variableName,
        params,
      );
    }

    if (
      !form().isEdit &&
      typeof props.widget.eventInfo[OnlineFormEventType.AFTER_LOAD_TABLE_DATA] === 'function'
    ) {
      res.data.dataList = await props.widget.eventInfo[OnlineFormEventType.AFTER_LOAD_TABLE_DATA](
        res.data.dataList,
        form().instanceData(),
      );
    }
    if (props.widget && props.widget.props.treeFlag && props.widget.props.parentIdColumn) {
      res.data.dataList = treeDataTranslate(
        res.data.dataList,
        primaryColumnName.value,
        props.widget.props.parentIdColumn,
      );
    }
    selectRows.value = [];
    return {
      dataList: res.data.dataList,
      totalCount: res.data.totalCount,
    };
  } catch (e) {
    console.error(e);
    throw e;
  }
};

const loadTableDataVerify = () => {
  return true;
};

const onSelectRowChange = (rows: ANY_OBJECT[]) => {
  selectRows.value = rows;
};

const onOperationClick = (operation: ANY_OBJECT, row: ANY_OBJECT | null) => {
  if (form().isEdit) return;
  if (operation.type === SysCustomWidgetOperationType.BATCH_DELETE) {
    onBatchDelete();
  } else if (operation.type === SysCustomWidgetOperationType.DELETE) {
    if (row) onDeleteRow(row);
  } else if (operation.type === SysCustomWidgetOperationType.EXPORT) {
    onExport(operation);
  } else if (operation.type === SysCustomWidgetOperationType.IMPORT) {
    onImport(operation, row);
  } else if (operation.type === SysCustomWidgetOperationType.PRINT) {
    form().onPrint(operation, row, selectRows.value, props.widget.showName);
  } else if (operation.type === SysCustomWidgetOperationType.START_FLOW) {
    console.log('启动流程');
    form().onStartFlow(operation, row);
  } else if (operation.type === SysCustomWidgetOperationType.UPDATE) {
    onUpdate(operation, row);
  } else if (operation.type === SysCustomWidgetOperationType.SCRIPT) {
    form()
      .handlerScriptOperation(operation, row)
      .then(() => {
        refreshTable(true);
      })
      .catch(e => {
        console.warn(e);
      });
  } else {
    let updateIdList = [];
    if (operation.type === SysCustomWidgetOperationType.UPDATE_DIALOG) {
      // 弹窗更新操作
      if (operation.rowOperation) {
        // 单条更新
        if (row == null) {
          ElMessage.error('请选择要更新的数据！');
          return;
        }
        updateIdList = [row[primaryColumnName.value]];
      } else {
        // 批量更新
        if (selectRows.value.length <= 0) {
          ElMessage.error('请选择要更新的数据！');
          return;
        }
        updateIdList = selectRows.value.map(item => {
          return item[primaryColumnName.value];
        });
      }
    }
    form().handlerOperation(operation, {
      isEdit: form().isEdit,
      isUpdate: operation.type === SysCustomWidgetOperationType.UPDATE_DIALOG,
      updateIdList: updateIdList,
      rowData: row,
      masterTableData: props.masterTableData || row,
      callback: () => {
        refreshTable();
      },
    });
  }
};

const onUpdate = (operation: ANY_OBJECT | null, row: ANY_OBJECT | null = null) => {
  if (operation == null) return;
  let table = form().tableMap.get(props.widget.bindData.tableId);
  let params = {
    datasourceId: table.datasource.datasourceId,
    relationId: (table.relation || {}).relationId,
    masterData: {},
    slaveData: {},
  };
  if (operation.relationId != null) {
    // 更新从表
    params.slaveData = operation.updateColumnList.reduce((pre, cur) => {
      pre[cur.updateColumnName] = cur.updateValue;
      return pre;
    }, {});
  } else {
    // 更新主表
    params.masterData = operation.updateColumnList.reduce((pre, cur) => {
      pre[cur.updateColumnName] = cur.updateValue;
      return pre;
    }, {});
  }
  if (!operation.rowOperation) {
    // 批量更新
    if (selectRows.value.length <= 0) {
      ElMessage.error('请选择要更新的数据！');
      return;
    }
    params.dataIdList = selectRows.value.map(item => {
      return item[primaryColumnName.value];
    });
  } else {
    // 单条更新
    if (row == null) {
      ElMessage.error('请选择要更新的数据！');
      return;
    }
    params.dataIdList = [row[primaryColumnName.value]];
  }
  let httpCall;
  let url;
  if (params.relationId) {
    httpCall = post(
      API_CONTEXT +
        '/online/onlineOperation/updateOneToManyRelationBatch/' +
        table.datasource.variableName,
      params,
    );
  } else {
    httpCall = post(
      API_CONTEXT +
        '/online/onlineOperation/updateDatasourceBatch/' +
        table.datasource.variableName,
      params,
    );
  }
  httpCall
    .then(res => {
      ElMessage.success(operation.name + '成功！');
      refreshTable(true);
    })
    .catch(e => {
      console.warn(e);
    });
};

const onBatchDelete = () => {
  if (selectRows.value.length <= 0) {
    ElMessage.error('请选择要批量删除的数据！');
    return;
  }
  ElMessageBox.confirm('是否删除选中数据？', '', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
  }).then(() => {
    let table = form().tableMap.get(props.widget.bindData.tableId);
    let params = {
      datasourceId: table.datasource.datasourceId,
      relationId: (table.relation || {}).relationId,
      dataIdList: selectRows.value.map(item => {
        return item[primaryColumnName.value];
      }),
    };

    let httpCall;
    if (params.relationId) {
      httpCall = post(
        API_CONTEXT +
          '/online/onlineOperation/deleteBatchOneToManyRelation/' +
          table.datasource.variableName,
        params,
      );
    } else {
      httpCall = post(
        API_CONTEXT +
          '/online/onlineOperation/deleteBatchDatasource/' +
          table.datasource.variableName,
        params,
      );
    }
    httpCall
      .then(() => {
        ElMessage.success('删除成功！');
        refreshTable(true);
      })
      .catch(e => {
        console.warn(e);
      });
  });
};

const onDeleteRow = (row: ANY_OBJECT) => {
  ElMessageBox.confirm('是否删除当前数据？', '', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
  })
    .then(() => {
      let table = form().tableMap.get(props.widget.bindData.tableId);
      let params = {
        datasourceId: table.datasource.datasourceId,
        relationId: (table.relation || {}).relationId,
        dataId: row[primaryColumnName.value],
      };
      let httpCall = null;
      if (params.relationId) {
        httpCall = post(
          API_CONTEXT +
            '/online/onlineOperation/deleteOneToManyRelation/' +
            table.datasource.variableName,
          params,
        );
      } else {
        httpCall = post(
          API_CONTEXT + '/online/onlineOperation/deleteDatasource/' + table.datasource.variableName,
          params,
        );
      }

      httpCall
        .then(() => {
          ElMessage.success('删除成功！');
          refreshTable(true);
        })
        .catch(e => {
          console.warn(e);
        });
    })
    .catch(() => {
      // on cancel
    });
};

const onImport = (operation: ANY_OBJECT, file: ANY_OBJECT | null) => {
  console.log(operation, file);
  let table = form().tableMap.get(props.widget.bindData.tableId);
  if (file == null) {
    ElMessage.error('请选择要导入的文件！');
    return;
  }
  if (table == null) {
    ElMessage.error('未找到数据源！');
    return;
  }
  let url = '/admin/online/onlineOperation/importDatasource/' + table.datasource.variableName;
  let params = {
    datasourceId: table.datasource.datasourceId,
    importColumnIds: (operation.exportColumnList || [])
      .sort((val1: ANY_OBJECT, val2: ANY_OBJECT) => {
        return val1.showOrder - val2.showOrder;
      })
      .map((item: ANY_OBJECT) => {
        return item.columnId;
      }),
    duplicateVerifyColumns: (operation.exportColumnList || [])
      .filter(item => {
        return item.duplicateCheckColumn;
      })
      .map(item => {
        return item.columnId;
      }),
    skipHeader: operation.skipHeader,
    importFile: file,
  };
  fetchUpload(url, params)
    .then(() => {
      ElMessage.success('导入成功！');
      refreshTable(true);
    })
    .catch(e => {
      ElMessage.error(e);
    });
};

const onExport = (operation: ANY_OBJECT) => {
  ElMessageBox.confirm('是否导出表格数据？', '', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
  }).then(async () => {
    let table = form().tableMap.get(props.widget.bindData.tableId);
    let params = {
      datasourceId: table.datasource.datasourceId,
      relationId: (table.relation || {}).relationId,
      filterDtoList: [],
      exportInfoList: (operation.exportColumnList || []).sort(
        (val1: ANY_OBJECT, val2: ANY_OBJECT) => {
          return val1.showOrder - val2.showOrder;
        },
      ),
    };

    if (props.widget.relation != null) {
      params.filterDtoList.push({
        tableName: props.widget.table.tableName,
        columnName: props.widget.relation.slaveColumn.columnName,
        filterType: SysOnlineColumnFilterType.EQUAL_FILTER,
        columnValue: (props.masterTableData || {})[props.widget.relation.masterColumn.columnName],
      });
    }

    let queryString = getQueryString();
    // 模糊查询
    if (
      Array.isArray(props.widget.props.likeQueryColumn) &&
      props.widget.props.likeQueryColumn.length > 0 &&
      queryString != null &&
      queryString !== ''
    ) {
      let queryColumn = props.widget.props.likeQueryColumn
        .map(item => {
          return item.join('.');
        })
        .join(',');
      if (!Array.isArray(params.filterDtoList)) params.filterDtoList = [];
      params.filterDtoList.push({
        columnName: queryColumn,
        filterType: 14,
        columnValue: queryString,
      });
    }

    if (
      !form().isEdit &&
      typeof props.widget.eventInfo[OnlineFormEventType.BEFORE_LOAD_TABLE_DATA] === 'function'
    ) {
      params = await props.widget.eventInfo[OnlineFormEventType.BEFORE_LOAD_TABLE_DATA](
        params,
        form().instanceData(),
      );
    }

    if (params == null) {
      throw new Error();
    }

    try {
      if (params.relationId) {
        await download(
          API_CONTEXT +
            '/online/onlineOperation/exportByOneToManyRelationId/' +
            table.datasource.variableName,
          params,
          props.widget.showName + '.xlsx',
        );
      } else {
        await download(
          API_CONTEXT +
            '/online/onlineOperation/exportByDatasourceId/' +
            table.datasource.variableName,
          params,
          props.widget.showName + '.xlsx',
        );
      }
      ElMessage.success('导出成功！');
    } catch (e) {
      ElMessage.error(e);
    }
  });
};

let paged = props.widget.props.treeFlag ? false : props.widget.props.paged;

const tableOptions: TableOptions<ANY_OBJECT> = {
  loadTableData: loadTableData,
  verifyTableParameter: loadTableDataVerify,
  paged: paged,
};
const queryTableWidget = reactive(useTable(tableOptions));

onMounted(() => {
  queryTableWidget.refreshTable();
});
</script>
